package com.zbkj.service.sfexpress;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.zbkj.dal.base.enums.ExpressOrderPayMethodType;
import com.zbkj.dal.common.utils.JsonUtil;
import com.zbkj.service.sfexpress.order.*;
import com.zbkj.service.sfexpress.pickup.CheckPickupTimeMsgData;
import com.zbkj.service.sfexpress.pickup.PickupTimeV1_1Res;
import com.zbkj.service.sfexpress.print.PrintWayBillsMsgData;
import com.zbkj.service.sfexpress.response.SFResult;
import com.zbkj.service.sfexpress.response.SFResultData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 484
 */
@Slf4j
@Component
public class CallExpressNewAPIService {

    @Autowired
    private SFExpressClient smsExpressClient;

    /**
     * 顾客编码
     */
    @Value("${express.sf.client-code:HJGWHHXNBTPE}")
    private String clientCode;

    /**
     * 校验码
     */
    @Value("${express.sf.check-code:3tcBbQCU4axGzmvrO4wN5PgTgbR4805J}")
    private String checkCode;

    /**
     * 沙箱环境的地址
     */
    @Value("${express.sf.call-url:https://sfapi-sbox.sf-express.com/std/service}")
    private String callUrl;

    /**
     * 生产环境的地址
     */
    private static final String CALL_URL_PROD = "https://sfapi.sf-express.com/std/service";


    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Nullable
    public CreateOrderMsgDataRes createOrder(String orderId,
                                             String productName,
                                             LocalDateTime pickupAppointEndTime,
                                             String senderPickupCode,
                                             ExpressOrderPayMethodType expressOrderPayMethodType,
                                             List<ContactInfo> contactInfo) {
        try {
            CreateOrderMsgData createOrderMsgData = new CreateOrderMsgData();
            createOrderMsgData.setLanguage("zh-CN");
            createOrderMsgData.setOrderId(orderId);
            createOrderMsgData.setIsReturnRoutelabel(1);
            createOrderMsgData.setIsGenWaybillNo(1);
            createOrderMsgData.setIsDocall(1);
            createOrderMsgData.setPayMethod(expressOrderPayMethodType.getCode());
            // 扩展信息
            ArrayList<ExtraInfoList> extraInfoLists = new ArrayList<>();
            if (ObjectUtil.isNotNull(pickupAppointEndTime)) {
                extraInfoLists.add(new ExtraInfoList(pickupAppointEndTime.format(formatter), "pickupAppointEndTime"));
            }
            if (ObjectUtil.isNotNull(senderPickupCode)) {
                extraInfoLists.add(new ExtraInfoList(senderPickupCode, "senderPickupCode"));
            }
            createOrderMsgData.setExtraInfoList(extraInfoLists);
            // 托运物信息
            CargoDetail cargoDetail = new CargoDetail();
            cargoDetail.setName(productName);
            createOrderMsgData.setCargoDetails(Collections.singletonList(cargoDetail));
            // 收寄方信息
            createOrderMsgData.setContactInfoList(contactInfo);
            SFResult<String> result = smsExpressClient.expReceCreateOrder(createOrderMsgData);
            if (BooleanUtil.isTrue(result.getSuccess())) {
                TypeReference<SFResultData<CreateOrderMsgDataRes>> typeReference = new TypeReference<SFResultData<CreateOrderMsgDataRes>>() {
                };
                SFResultData<CreateOrderMsgDataRes> resultData = JsonUtil.parseObject(result.getApiResultData(), typeReference);
                Assert.notNull(resultData, "响应异常");
                if (BooleanUtil.isTrue(resultData.getSuccess())) {
                    return resultData.getMsgData();
                } else {
                    log.error("下单失败:{}", JsonUtil.toJSONString(resultData));
                }
            } else {
                log.error("createOrder error:{}", JsonUtil.toJSONString(result));
            }
        } catch (Exception e) {
            log.error("访问顺丰接口: 创建订单失败. ", e);
        }
        return null;
    }

    /**
     * 取消订单
     *
     * @param orderId 订单号
     * @return 取消结果
     */
    public Boolean cancelOrder(String orderId) {
        ExpReceUpdateOrder expReceUpdateOrder = new ExpReceUpdateOrder();
        expReceUpdateOrder.setDealType(2);
        expReceUpdateOrder.setOrderId(orderId);
        return getaExpReceUpdateOrderResult(expReceUpdateOrder);
    }

    /**
     * 更新上门揽收时间
     *
     * @param orderId     订单 ID
     * @param sendStartTm 上门开始时间
     * @return 更新结果
     */
    public Boolean updateOrderPickupTime(String orderId, String waybillNo, LocalDateTime sendStartTm) {
        ExpReceUpdateOrder expReceUpdateOrder = new ExpReceUpdateOrder();
        expReceUpdateOrder.setDealType(1);
        expReceUpdateOrder.setOrderId(orderId);
        // 物流信息
        ExpReceUpdateOrder.WaybillNoInfo waybillNoInfo = new ExpReceUpdateOrder.WaybillNoInfo();
        waybillNoInfo.setWaybillType(1);
        waybillNoInfo.setWaybillNo(waybillNo);
        expReceUpdateOrder.setWaybillNoInfoList(Collections.singletonList(waybillNoInfo));
        // 更改的预约时间
        expReceUpdateOrder.setSendStartTm(sendStartTm);
        return getaExpReceUpdateOrderResult(expReceUpdateOrder);
    }

    private Boolean getaExpReceUpdateOrderResult(ExpReceUpdateOrder expReceUpdateOrder) {
        SFResult<String> sfResult = smsExpressClient.expReceUpdateOrder(expReceUpdateOrder);
        if (BooleanUtil.isTrue(sfResult.getSuccess())) {
            TypeReference<SFResultData<ExpReceUpdateOrderRes>> typeReference = new TypeReference<SFResultData<ExpReceUpdateOrderRes>>() {
            };
            SFResultData<ExpReceUpdateOrderRes> resultData = JsonUtil.parseObject(sfResult.getApiResultData(), typeReference);
            Assert.notNull(resultData, "响应异常");
            if (BooleanUtil.isTrue(resultData.getSuccess())) {
                return Objects.equals(resultData.getMsgData().getResStatus(), 2);
            } else {
                log.error("下单失败:{}", JsonUtil.toJSONString(resultData));
            }
        } else {
            log.error("cancelOrder error:{}", JsonUtil.toJSONString(sfResult));
        }
        return false;
    }

    public PickupTimeV1_1Res checkPickupTime(String address, String cityCode, LocalDateTime sendTime, String province, String cityName, String county) {
        try {
            CheckPickupTimeMsgData createOrderMsgData = new CheckPickupTimeMsgData();
            createOrderMsgData.setAddress(address);
            createOrderMsgData.setCityCode(cityCode);
            createOrderMsgData.setAddressType("1");
            createOrderMsgData.setSendTime(sendTime.format(formatter));
            createOrderMsgData.setSysCode("qiao");
            createOrderMsgData.setVersion("1.1");
            createOrderMsgData.setProvince(province);
            createOrderMsgData.setCity(cityName);
            createOrderMsgData.setCounty(county);
            SFResult<String> response = smsExpressClient.checkPickupTime(createOrderMsgData);
            if (response.getSuccess()) {
                TypeReference<SFResultData<PickupTimeV1_1Res>> typeReference = new TypeReference<SFResultData<PickupTimeV1_1Res>>() {
                };
                SFResultData<PickupTimeV1_1Res> resultData = JsonUtil.parseObject(response.getApiResultData(), typeReference);
                Assert.notNull(resultData, "响应异常");
                if (BooleanUtil.isTrue(resultData.getSuccess())) {
                    return resultData.getMsgData();
                }
            } else {
                log.error("checkPickupTime error:{}", JsonUtil.toJSONString(response));
            }
        } catch (Exception e) {
            log.error("访问顺丰接口: 检测提货时间失败. ", e);
        }
        return PickupTimeV1_1Res.error();
    }

    public Boolean printWayBills(Collection<String> wayBillNo) {
        try {
            PrintWayBillsMsgData printWayBillsMsgData = new PrintWayBillsMsgData();
            printWayBillsMsgData.setTemplateCode("fm_76130_standard_HJGWHHXNBTPE");
            // 转换成Documents
            List<PrintWayBillsMsgData.Documents> collect = wayBillNo.stream().map(wayBill -> {
                PrintWayBillsMsgData.Documents documents = new PrintWayBillsMsgData.Documents();
                documents.setMasterWaybillNo(wayBill);
                return documents;
            }).collect(Collectors.toList());
            printWayBillsMsgData.setDocuments(collect);
            SFResult<String> response = smsExpressClient.printWayBills(printWayBillsMsgData);
            if (response.getSuccess()) {
                SFResultData<?> resultData = JsonUtil.parseObject(response.getApiResultData(), SFResultData.class);
                Assert.notNull(resultData, "云打印面单响应异常");
                return BooleanUtil.isTrue(resultData.getSuccess());
            } else {
                log.error("checkPickupTime error:{}", JsonUtil.toJSONString(response));
            }
        } catch (Exception e) {
            log.error("调用云打印电子面单失败");
        }
        return false;
    }


}
